home *** CD-ROM | disk | FTP | other *** search
/ Winzipper / Winzipper_ISO.iso / programming / oracle7 7.2 / DB / UTIL72 / PRVTLOCK.SQL < prev    next >
Encoding:
Text File  |  1995-05-09  |  9.6 KB  |  319 lines

  1. rem 
  2. rem $Header: prvtlock.sql 7020200.1 95/02/15 18:27:17 cli Generic<base> $ 
  3. rem 
  4. Rem
  5. Rem    NAME
  6. Rem      prvtlock.sql - locking routines provided by Oracle
  7. Rem    DESCRIPTION
  8. Rem      These are private functions to be released in PL/SQL binary form.
  9. Rem      See below
  10. Rem    RETURNS
  11. Rem
  12. Rem    NOTES
  13. Rem     The procedural option is needed to use this facility.
  14. Rem
  15. Rem     Lockids from 2000000000 to 2147483647 are reserved for products
  16. Rem     supplied by Oracle:
  17. Rem
  18. Rem       Package                     Lock id range
  19. Rem       =================================================
  20. Rem       dbms_alert                  2000000000-2000002041
  21. Rem       dbms_alert                  2000002042-2000003063
  22. Rem
  23. Rem    MODIFIED   (MM/DD/YY)
  24. Rem     pgreenwa   11/14/94 -  merge changes from branch 1.1.710.3
  25. Rem     pgreenwa   11/10/94 -  bug #248150: fix timeouts on dbms_lock_allocated
  26. Rem     wmaimone   04/08/94 -  merge changes from branch 1.1.710.2
  27. Rem     adowning   03/29/94 -  merge changes from branch 1.1.710.1
  28. Rem     wmaimone   02/22/94 -  use create or replace
  29. Rem     adowning   02/04/94 -  Branch_for_patch
  30. Rem     adowning   02/04/94 -  Creation
  31. Rem     adowning   02/02/94 -  split file into public / private binary files
  32. Rem     rkooi      12/03/92 -  change comments 
  33. Rem     rkooi      11/25/92 -  return 5 instead of 6 per spec 
  34. Rem     rkooi      11/24/92 -  check for nulls 
  35. Rem     rkooi      11/18/92 -  add comments 
  36. Rem     rkooi      08/20/92 -  comments and cleanup 
  37. Rem     rkooi      06/29/92 -  add some comments 
  38. Rem     rkooi      05/30/92 -  fix timeout problems 
  39. Rem     rkooi      04/30/92 -  add some comments 
  40. Rem     rkooi      04/25/92 -  misc change 
  41. Rem     rkooi      04/12/92 -  Creation 
  42.  
  43. Rem This script must be run as user SYS
  44.  
  45. REM ************************************************************
  46. REM THIS PACKAGE MUST NOT BE MODIFIED BY THE CUSTOMER.  DOING SO
  47. REM COULD CAUSE INTERNAL ERRORS AND CORRUPTIONS IN THE RDBMS.
  48. REM FOR INSTANCE, THE PSD* ROUTINES MUST NOT BE CALLED DIRECTLY
  49. REM BY ANY CLIENT AND MUST REMAIN PRIVATE TO THIS PACKAGE.
  50. REM ************************************************************
  51.  
  52. drop table dbms_lock_allocated
  53. /
  54. create table dbms_lock_allocated(
  55.     name        varchar2(128) primary key,
  56.     lockid        integer,
  57.     expiration    date)
  58. /
  59. drop sequence dbms_lock_id
  60. /
  61.  
  62. create sequence dbms_lock_id start with 1073741824 maxvalue 1999999999
  63. /
  64.  
  65. create or replace package body dbms_lock is
  66.  
  67.   procedure psdlgt(id binary_integer, lockmode binary_integer, 
  68.                    maxholders binary_integer, timeout binary_integer, 
  69.                    release_on_commit binary_integer, 
  70.                    global_lock binary_integer, status in out binary_integer);
  71.     pragma interface (C, psdlgt);
  72.   procedure psdlcv(id binary_integer, lockmode binary_integer,
  73.              maxholders binary_integer, timeout binary_integer,
  74.            status in out binary_integer);
  75.     pragma interface (C, psdlcv);
  76.   procedure psdlrl(id binary_integer, status in out binary_integer);
  77.     pragma interface (C, psdlrl);
  78.   procedure psdwat(tens_of_millisecs binary_integer);
  79.     pragma interface (C, psdwat);
  80.  
  81.   procedure convertback(lockhandle varchar2,
  82.                         id out integer,
  83.                         status out integer) is
  84.     tmpid integer;
  85.   begin
  86.     begin
  87.       status := 0;
  88.       id := -1;
  89.       if length(lockhandle)=0 then
  90.         status := 5;
  91.       else
  92.         tmpid := to_number(substr(lockhandle,1,10));
  93.         if (tmpid <> to_number(substr(lockhandle,11,10))) then
  94.           status := 5;
  95.         elsif (tmpid mod 239) <> to_number(substr(lockhandle,21,10)) then
  96.           status := 5;
  97.         elsif tmpid<1073741824 or tmpid>1999999999 then
  98.           status := 3;
  99.         else
  100.           id := tmpid;
  101.         end if;
  102.       end if;
  103.     exception when others then
  104.       status := 5;
  105.     end;
  106.   end;
  107.  
  108.   function  internal_request(id integer,
  109.                     lockmode integer,
  110.                     timeout integer,
  111.                     release_on_commit boolean,
  112.                     global_lock boolean)
  113.             return integer is
  114.   arg1    binary_integer;
  115.   arg2    binary_integer;
  116.   arg3    binary_integer;
  117.   arg4    binary_integer;
  118.   arg5    binary_integer;
  119.   arg6    binary_integer;
  120.   status  binary_integer;
  121.   begin
  122.     if timeout<0 or lockmode<1 or lockmode>6 then
  123.       return 3;
  124.     end if;
  125.     if id is null or lockmode is null or timeout is null then
  126.       return 3;
  127.     end if;
  128.     arg1 := id;
  129.     arg2 := lockmode;
  130.     arg3 := 0;
  131.     if timeout>maxwait then
  132.       arg4 := maxwait;
  133.     else
  134.       arg4 := timeout;
  135.     end if;
  136.     if release_on_commit then
  137.       arg5 := 1;
  138.     else
  139.       arg5 := 0;
  140.     end if;
  141.     if global_lock then
  142.       arg6 := 1;
  143.     else
  144.       arg6 := 0;
  145.     end if;
  146.     psdlgt(arg1, arg2, arg3, arg4, arg5, arg6, status);
  147.     return status;
  148.   end;
  149.  
  150.   function  request(lockhandle varchar2,
  151.                     lockmode integer default x_mode, 
  152.                     timeout integer default maxwait,
  153.                     release_on_commit boolean default FALSE)
  154.             return integer is
  155.     id integer;
  156.     status integer;
  157.   begin
  158.     convertback(lockhandle, id, status);
  159.     if status <> 0 then
  160.       return status;
  161.     end if;
  162.     return internal_request(id, lockmode, timeout, release_on_commit, TRUE);
  163.   end;
  164.  
  165.   function  request(id integer,
  166.                     lockmode integer default x_mode, 
  167.                     timeout integer default maxwait,
  168.                     release_on_commit boolean default FALSE)
  169.             return integer is
  170.   begin
  171.     if id<0 or (id>1073741823 and id<2000000000) then
  172.       return 3;
  173.     end if;
  174.     return internal_request(id, lockmode, timeout, release_on_commit, TRUE);
  175.   end;
  176.  
  177.   function internal_convert(id integer, 
  178.                    lockmode integer, 
  179.                    timeout number)
  180.            return integer is
  181.     arg1   binary_integer;
  182.     arg2   binary_integer;
  183.     arg3   binary_integer;
  184.     arg4   binary_integer;
  185.     status binary_integer;
  186.   begin
  187.     if timeout<0 or lockmode<1 or lockmode>6 then
  188.       return 3;
  189.     end if;
  190.     if id is null or lockmode is null or timeout is null then
  191.       return 3;
  192.     end if;
  193.     arg1 := id;
  194.     arg2 := lockmode;
  195.     arg3 := 0;
  196.     if timeout>maxwait then
  197.       arg4 := maxwait;
  198.     else
  199.       arg4 := timeout;
  200.     end if;
  201.     psdlcv(arg1, arg2, arg3, arg4, status);
  202.     return status;
  203.   end;
  204.  
  205.   function convert(lockhandle varchar2,
  206.                    lockmode integer, 
  207.                    timeout number default maxwait)
  208.            return integer is
  209.     id integer;
  210.     status integer;
  211.   begin
  212.     convertback(lockhandle, id, status);
  213.     if status <> 0 then
  214.       return status;
  215.     end if;
  216.     return internal_convert(id, lockmode, timeout);
  217.   end;
  218.  
  219.   function convert(id integer, 
  220.                    lockmode integer, 
  221.                    timeout number default maxwait)
  222.            return integer is
  223.   begin
  224.     if id<0 or (id>1073741823 and id<2000000000) then
  225.       return 3;
  226.     end if;
  227.     return internal_convert(id, lockmode, timeout);
  228.   end;
  229.  
  230.   function internal_release(id integer) return integer is
  231.     arg1   binary_integer;
  232.     status binary_integer;
  233.   begin
  234.     if id is null then
  235.       return 3;
  236.     end if;
  237.     arg1 := id;
  238.     psdlrl(arg1, status);
  239.     return status;
  240.   end;
  241.  
  242.   function release(lockhandle varchar2) return integer is
  243.     id integer;
  244.     status integer;
  245.   begin
  246.     convertback(lockhandle, id, status);
  247.     if status <> 0 then
  248.       return status;
  249.     end if;
  250.     return internal_release(id);
  251.   end;
  252.  
  253.   function release(id integer) return integer is
  254.   begin
  255.     if id<0 or (id>1073741823 and id<2000000000) then
  256.       return 3;
  257.     end if;
  258.     return internal_release(id);
  259.   end;
  260.  
  261.   procedure sleep(seconds number) is
  262.     arg1   binary_integer;
  263.   begin
  264.     arg1 := seconds*100;
  265.     psdwat(arg1);
  266.   end;
  267.  
  268.   procedure allocate_unique(lockname in varchar2, 
  269.                 lockhandle out varchar2,
  270.                 expiration_secs in integer default 864000) is
  271.     lockid integer;
  272.     cursor c1(lname varchar2) is 
  273.       select lockid from dbms_lock_allocated where name = c1.lname for update;
  274.     trycount integer := 0;
  275.   begin
  276.     <<retryloop>>
  277.     loop
  278.       open c1(lockname);
  279.       fetch c1 into lockid;
  280.       if c1%notfound then
  281.         close c1;
  282.         if trycount >= 1 then
  283.           raise_application_error(-20000,
  284.            'ORU-10003: Unable to find or insert lock '''
  285.             || lockname || ''' into catalog dbms_lock_allocated.');
  286.         end if;
  287.         begin
  288.           -- we are first to try to allocate this lock.  So allocate
  289.           -- a lockid.
  290.           select dbms_lock_id.nextval into lockid from dual;
  291.           -- do periodic cleanout.
  292.           if (lockid mod 100) = 0 then
  293.             delete dbms_lock_allocated where expiration < sysdate;
  294.             commit;
  295.           end if;
  296.           insert into dbms_lock_allocated values (lockname, lockid, 
  297.             sysdate + (expiration_secs/86400));
  298.           exit retryloop;
  299.         exception when dup_val_on_index then
  300.           -- someone must have inserted this key into the table between the
  301.           -- the time we did the select and the time we tried to insert.
  302.           -- So retry.
  303.           trycount := trycount+1;
  304.         end;
  305.       else
  306.         update dbms_lock_allocated 
  307.           set expiration = sysdate + (expiration_secs/86400)
  308.           where current of c1;
  309.         close c1;
  310.         exit retryloop;
  311.       end if;
  312.     end loop;
  313.     lockhandle := to_char(lockid)||to_char(lockid)||to_char(lockid mod 239);
  314.     commit;
  315.   end;
  316.  
  317. end;
  318. /
  319.